﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp
{
    public class demo_task
    {
        public static void demo()
        {
            CancellationTokenSource tokenSource = new CancellationTokenSource();
            CancellationToken token = tokenSource.Token;

            Task t = new Task(() => { runlongtimeinback(); }, token);
        }

        private static void runlongtimeinback()
        {

        }

        static Task<TResult> Run<TResult>(Func<TResult> function)
        {
            var tcs = new TaskCompletionSource<TResult>();
            new Thread(() =>
            {
                try { tcs.SetResult(function()); }
                catch (Exception ex) { tcs.SetException(ex); }
            }).Start();
            return tcs.Task;
        }

        public static void Begin()
        {
            Task task = new Task(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("Foo");
            });
            task.Start();
            Console.WriteLine(task.IsCompleted);  // False
            task.Wait();
            Console.WriteLine(task.IsCompleted);  // Yes

            Task task1 = Task.Factory.StartNew(
                () =>
                {
                    Thread.Sleep(1000);
                    Console.WriteLine("Factory Foo");
                }, TaskCreationOptions.LongRunning);


            Task<int> task2 = Task.Factory.StartNew<int>(
                () => { Thread.Sleep(1000); return 3; }
            );
            task2.ContinueWith(antecedent =>
            {
                int result = antecedent.Result;
                Console.WriteLine(result);          // print 3,ContinueWith will not block
            });

            Task taskException = new Task(() => { throw null; });
            taskException.Start();
            try
            {
                taskException.Wait();
            }
            catch (AggregateException aex)
            {
                if (aex.InnerException is NullReferenceException)
                    Console.WriteLine("Null!");
                else
                    throw;
            }

            /*
             * the comomn technology to use TaskCompletionSource,so we can encapsulate it to a Run method
             */
            var tcs = new TaskCompletionSource<int>();
            new Thread(() => { Thread.Sleep(5000); tcs.SetResult(42); }).Start();
            Task<int> taskT = tcs.Task;
            Console.WriteLine(taskT.Result);
            Task<int> taskSelf = Run(() => { Thread.Sleep(1000); return 42; });
            int value = taskSelf.Result;
        }
    }

    public static class TaskExtension
    {
        public static Task FailFastOnException(this Task task)
        {
            task.ContinueWith(c => Environment.FailFast("Task faulted", c.Exception),
                TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
            return task; 
        }
    }
}
